package com.potevio.simulator.task;


import com.potevio.simulator.common.CommonFlag;
import com.potevio.simulator.common.GetHexMessage;
import com.potevio.simulator.config.MsgTypeConst;
import com.potevio.simulator.entity.ChargeModelChargeMsg0x39;
import com.potevio.simulator.entity.ChargeModelChargeMsg0x3F;
import com.potevio.simulator.heart.HeartbeatClient;
import com.potevio.simulator.strategy.impl.Deal79Command;
import com.potevio.simulator.strategy.impl.Deal7FCommand;
import com.potevio.simulator.util.CarVINUtil;
import com.potevio.simulator.util.HexUtil;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName ChargeMsgTask
 * @Description: 充电过程定时任务
 * @Date 2021/5/11  15:40
 * @Author zyd
 */
public class ChargeMsgTask implements Runnable {
    private final static Logger LOGGER = LoggerFactory.getLogger(ChargeMsgTask.class);

    //电量x  （初始值加上随机数）
    public static BigDecimal quantityElectricity = new BigDecimal(0);
    //电能 （初始值加上随机数） 最终度数需要用到，初始度数加上电能
    public static int electricEnergy = 0;
    //充电时间x （0每次加上充电间隔）
    public static int chargeTime = 0;
    //初始度数 （每次加上电能）
    public static int InitMeterDegrees;
    //当前soc
    public static int currentSOC = Integer.valueOf(HexUtil.hex2Int(ChargeModelChargeMsg0x39.currentSOC));
    //发送停止充电报文（79，7F）where  ==4
    public static int send00Number = 1;
    public static boolean stopFlag = false;
    private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    /**
     * 0x17报文需要处理的字段集合
     */
    private static String[] fields = new String[]{"highVoltage", "lowVoltage", "highElectricCurrent",
            "highOneChargeVoltage", "highTemperature", "isChargeCode", "totalVoltage", "totalElectricCurrent",
            "highAllowOneVoltage", "batteryTemperature"};

    public Channel channel;

    public ChargeMsgTask() {
        this.channel = HeartbeatClient.channel;
    }

    @Override
    public void run() {
//        sendMsgTask();
        if(CommonFlag.messageSendFlag){
            LOGGER.info("时间="+SIMPLE_DATE_FORMAT.format(new Date()));
            send34Msg();
            //不同协议发送不同报文
            if(CommonFlag.version.equals("3.4a1")){
                send3FMsg();
            }else{
                send39Msg();
            }
            send31Msg();
            send17Msg();
            send18Msg();
            send3aMsg();
        }

        if(stopFlag){
            send00Number++;
            LOGGER.info("send00Number="+send00Number);
            if(send00Number == 4){
                LOGGER.info("枪号:"+CommonFlag.chargeNum);
                if("3.4a1".equals(CommonFlag.version)){
                    new Deal7FCommand().send7FMsg(channel);
                }else {
                    new Deal79Command().send79Msg(channel);
                }
                quantityElectricity = new BigDecimal(0);
                electricEnergy = 0;
                chargeTime = 0;
                InitMeterDegrees = 0;
                currentSOC = Integer.valueOf(HexUtil.hex2Int(ChargeModelChargeMsg0x39.currentSOC));
                send00Number = 1;
                stopFlag = Boolean.FALSE;
            }
        }
    }

    private void send3aMsg() {
        try {
            LOGGER.info("定时发送充电报文0x3a——msgLog");
            if("3.4a".equals(CommonFlag.version)){
                Map<String, LinkedHashMap<String, String>> map = new GetHexMessage().getDataDomain(MsgTypeConst.CHARGE_MODEL_BATTERY_INFO_MSG, "");
                channel.writeAndFlush(map);
            }else{
                Map<String, LinkedHashMap<String, String>> map = new HashMap<>();
                LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
                map.put("0x3a", null);
                channel.writeAndFlush(map);
            }

        } catch (Exception e) {
            LOGGER.error("0x3a报文发送异常：{}", e);
        }
    }

    /**
     * 发送报文定时任务
     */
    public void sendMsgTask() {
        try {
            // 从配置文件获取要定时执行的充电过程报文方法集合
            String[] methodsArr = HeartbeatClient.chargeMsgTaskMethods.split(",");
            // 要反射的类名
            String className = HeartbeatClient.chargeMsgTaskClass;
            for (int i = 0; i < methodsArr.length; i++) {
                // 方法名
                String methodName = "send" + methodsArr[i] + "Msg";
                // 通过配置文件反射指定的类
                Class c = Class.forName(className);
                // 实例化被反射的对象
                Object obj = c.newInstance();
                // 获取指定方法
                Method method = c.getMethod(methodName);
                // 执行方法
                method.invoke(obj);
            }
        } catch (Exception e) {
            LOGGER.error("充电过程报文定时任务异常：", e);
        }
    }

    /**
     * 0x34报文
     */
    public void send34Msg() {
        try {
            LOGGER.info("定时发送充电报文0x34——msgLog");
            Map<String, LinkedHashMap<String, String>> map = new GetHexMessage().getDataDomain(MsgTypeConst.CHARGE_MODEL_STATE_INFO_MSG);
            LinkedHashMap<String, String> chMap = map.get("0x34");
            Set<String> tempKey = chMap.keySet();
            Iterator<String> iterator1 = tempKey.iterator();
            //判断充电状态：1充电中 0启动
            if(HeartbeatClient.chargingPileState==1){
                while (iterator1.hasNext()){
                    String key2 = iterator1.next();
                    int num = 0;
                    // 电压
                    if ("chargeVoltage".equals(key2)) {
                        num = HexUtil.makeRandom(210f, 245f, 0).intValue();
                        chMap.put(key2, HexUtil.random2HexAndReverse(num));
                        //  电流+3200（偏移量）
                    } else if ("chargeCurrent".equals(key2)) {
                        num = HexUtil.makeRandom(110f, 90f, 0).intValue() + 3200;
                        chMap.put(key2, HexUtil.random2HexAndReverse(num));
                        // 输出功率
                    } else if ("outputPower".equals(key2)) {
                        num = HexUtil.makeRandom(70f, 60f, 0).intValue();
                        chMap.put(key2, HexUtil.random2HexAndReverse(num));
                    } else if ("chargeBatteryState".equals(key2)) {
                        chMap.put(key2, "01");
                    } else if ("executeOrgState".equals(key2)) {
                        chMap.put(key2, "02");
                    }
                }
                //根据桩协议不同修改充电类型的值,3.4或者3.4a1猜测在这里赋值没用，在多枪处理的时候赋值
                if("3.4a".equals(CommonFlag.version) || "3.4a1".equals(CommonFlag.version)){
                    chMap.put("chargeType","05");
                }
                //3.4不走多枪处理，在这里赋值
                if("3.4".equals(CommonFlag.version)){
                    chMap.put("chargeType","01");
                }
            }
            //设置枪数量
            if("3.4a".equals(CommonFlag.version)){
                chMap.put("chargeGunNum","02");
            }
            map.put("0x34", chMap);
            channel.writeAndFlush(map);
        } catch (Exception e) {
            LOGGER.error("0x34报文发送异常：{}", e);
        }
    }

    /**
     * 0x39报文
     */
    public  void send39Msg() {
        try {
            LOGGER.info("定时发送充电报文0x39——msgLog");
            Map<String, LinkedHashMap<String, String>> map = new GetHexMessage().getDataDomain(MsgTypeConst.CHARGE_MODEL_CHARGE_MSG);
            LinkedHashMap<String, String> chMap = map.get("0x39");
            Set<String> tempKey = chMap.keySet();
            Iterator<String> iterator1 = tempKey.iterator();
            if(HeartbeatClient.chargingPileState == 1){
                while (iterator1.hasNext()){
                    String key2 = iterator1.next();
                    BigDecimal bigDecimal;
                    // 电能
                    if ("cumulativeChargeKwh".equals(key2)) {
                        bigDecimal = HexUtil.makeRandom(3f, 1f, 2);
                        quantityElectricity = quantityElectricity.add(bigDecimal);
                        // 定额充电，到了设定电量自动停止
                        int i = quantityElectricity.multiply(new BigDecimal(100)).intValue();
                        if(i >= HeartbeatClient.ratedCharge * 100){
                            // 修改充电桩状态
//                            new CommonTask().updateChargeState();
                        }
                        String qeStr = HexUtil.random2HexAndReverse(i);
                        MsgTypeConst.chm_Map.get("0x39").put("cumulativeChargeKwh", qeStr);
                        chMap.put(key2, qeStr);
                        //  电量
                    } else if ("cumulativeChargeAh".equals(key2)) {
                        int temp = HexUtil.makeRandom(3f, 1f, 0).intValue();
                        electricEnergy = electricEnergy + temp;
                        String eeStr = HexUtil.random2HexAndReverse(electricEnergy);
                        MsgTypeConst.chm_Map.get("0x39").put("cumulativeChargeAh", eeStr);
                        chMap.put(key2, eeStr);
                        // 累计充电时间
                    } else if ("cumulativeChargeTime".equals(key2)) {
                        chargeTime = chargeTime + HeartbeatClient.chargeMsgInterval;
                        LOGGER.info("累计充电时长cumulativeChargeTime="+chargeTime);
                        String ctStr = "";
                        if(chargeTime <= 15 ){
                            ctStr = HexUtil.int2Hex(chargeTime) + "00";
                            LOGGER.info("小于15秒chargeTime="+ctStr);
                        }else {
                            ctStr = HexUtil.random2HexAndReverse(chargeTime);
                            LOGGER.info("大于15秒chargeTime="+ctStr);
                        }
                        MsgTypeConst.chm_Map.get("0x39").put("cumulativeChargeTime", ctStr);
                        chMap.put(key2, ctStr);
                        // 当前SOC
                    } else if ("currentSOC".equals(key2)) {
                        currentSOC++;
                        LOGGER.info("当前SOC——msgLog：" + currentSOC);
                        MsgTypeConst.chm_Map.get("0x39").put("chargeStartSOC", ChargeModelChargeMsg0x39.chargeStartSOC);
                        if (currentSOC >= 100) {
                            quantityElectricity = new BigDecimal(0);
                            electricEnergy = 0;
                            chargeTime = 0;
                            InitMeterDegrees = 0;
                            currentSOC = Integer.valueOf(HexUtil.hex2Int(ChargeModelChargeMsg0x39.currentSOC));
                            send00Number = 1;
                            stopFlag = false;
                            LOGGER.info("停止充电——msgLog。。。。。。。。。。。。。。。");
                        }
                        chMap.put(key2, HexUtil.int2Hex(currentSOC));
                        // 电表度数Kwh
                    }else if("ammeterDegrees".equals(key2)){
                        int meterDegrees = quantityElectricity.add(new BigDecimal(ChargeMsgTask.InitMeterDegrees)).multiply(new BigDecimal(100)).intValue();
                        LOGGER.info("最后一次电表度数：{}", meterDegrees);
                        String mdHexStr = HexUtil.random2HexAndReverse(meterDegrees);
                        mdHexStr = HexUtil.getIntervalByteNum(mdHexStr, "0x39", key2);
                        chMap.put(key2, mdHexStr);
                    }
                }
            }
            map.put("0x39", chMap);
            channel.writeAndFlush(map);
        } catch (Exception e) {
            LOGGER.error("0x39报文发送异常：{}", e);
        }
    }

    /**
     * 0x3F报文
     */
    public  void send3FMsg() {
        try {
            LOGGER.info("定时发送充电报文0x3F——msgLog");
            Map<String, LinkedHashMap<String, String>> map = new GetHexMessage().getDataDomain(MsgTypeConst.CHARGE_MODEL_CHARGE3F_MSG);
            LinkedHashMap<String, String> chMap = map.get("0x3F");
            Set<String> tempKey = chMap.keySet();
            Iterator<String> iterator1 = tempKey.iterator();
            if(HeartbeatClient.chargingPileState == 1){
                while (iterator1.hasNext()){
                    String key2 = iterator1.next();
                    BigDecimal bigDecimal;
                    // 电能
                    if ("cumulativeChargeKwh".equals(key2)) {
                        bigDecimal = HexUtil.makeRandom(3f, 1f, 2);
                        quantityElectricity = quantityElectricity.add(bigDecimal);
                        // 定额充电，到了设定电量自动停止
                        int i = quantityElectricity.multiply(new BigDecimal(100)).intValue();
                        if(i >= HeartbeatClient.ratedCharge * 100){
                            // 修改充电桩状态
//                            new CommonTask().updateChargeState();
                        }
                        String qeStr = HexUtil.random2HexAndReverse(i);
                        MsgTypeConst.chm_Map.get("0x3F").put("cumulativeChargeKwh", qeStr);
                        chMap.put(key2, qeStr);
                        //  电量
                    } else if ("cumulativeChargeAh".equals(key2)) {
                        int temp = HexUtil.makeRandom(3f, 1f, 0).intValue();
                        electricEnergy = electricEnergy + temp;
                        String eeStr = HexUtil.random2HexAndReverse(electricEnergy);
                        MsgTypeConst.chm_Map.get("0x3F").put("cumulativeChargeAh", eeStr);
                        chMap.put(key2, eeStr);
                        // 累计充电时间
                    } else if ("cumulativeChargeTime".equals(key2)) {
                        chargeTime = chargeTime + HeartbeatClient.chargeMsgInterval;
                        LOGGER.info("累计充电时长cumulativeChargeTime="+chargeTime);
                        String ctStr = "";
                        if(chargeTime <= 15 ){
                            ctStr = HexUtil.int2Hex(chargeTime) + "00";
                            LOGGER.info("小于15秒chargeTime="+ctStr);
                        }else {
                            ctStr = HexUtil.random2HexAndReverse(chargeTime);
                            LOGGER.info("大于15秒chargeTime="+ctStr);
                        }
                        MsgTypeConst.chm_Map.get("0x3F").put("cumulativeChargeTime", ctStr);
                        chMap.put(key2, ctStr);
                        // 当前SOC
                    } else if ("currentSOC".equals(key2)) {
                        currentSOC++;
                        LOGGER.info("当前SOC——msgLog：" + currentSOC);
                        MsgTypeConst.chm_Map.get("0x3F").put("chargeStartSOC", ChargeModelChargeMsg0x3F.chargeStartSOC);
                        if (currentSOC >= 100) {
                            quantityElectricity = new BigDecimal(0);
                            electricEnergy = 0;
                            chargeTime = 0;
                            InitMeterDegrees = 0;
                            currentSOC = Integer.valueOf(HexUtil.hex2Int(ChargeModelChargeMsg0x3F.currentSOC));
                            send00Number = 1;
                            stopFlag = false;
                            LOGGER.info("停止充电——msgLog。。。。。。。。。。。。。。。");
                        }
                        chMap.put(key2, HexUtil.int2Hex(currentSOC));
                        // 电表度数Kwh
                    }else if("ammeterDegrees".equals(key2)){
                        int meterDegrees = quantityElectricity.add(new BigDecimal(ChargeMsgTask.InitMeterDegrees)).multiply(new BigDecimal(100)).intValue();
                        LOGGER.info("最后一次电表度数：{}", meterDegrees);
                        String mdHexStr = HexUtil.random2HexAndReverse(meterDegrees);
                        mdHexStr = HexUtil.getIntervalByteNum(mdHexStr, "0x3F", key2);
                        chMap.put(key2, mdHexStr);
                    }
                }
            }
            map.put("0x3F", chMap);
            channel.writeAndFlush(map);
        } catch (Exception e) {
            LOGGER.error("0x3F报文发送异常：{}", e);
        }
    }

    /**
     * 0x31报文
     */
    public void send31Msg() {
        try {
            LOGGER.info("定时发送充电报文0x31——msgLog");
            Map<String, LinkedHashMap<String, String>> map = new GetHexMessage().getDataDomain(MsgTypeConst.CHARGE_PILE_POPULATION_STATE_MSG);
            channel.writeAndFlush(map);
        } catch (Exception e) {
            LOGGER.error("0x31报文发送异常：{}", e);
        }
    }

    /**
     * 0x17报文
     */
    public void send17Msg() {
        try {
            LOGGER.info("定时发送充电报文0x17——msgLog");
            Map<String, LinkedHashMap<String, String>> map = new GetHexMessage().getDataDomain(MsgTypeConst.CHARGE_MODEL_PARAM_SELECT_MSG_17);
            LinkedHashMap<String, String> chMap = map.get("0x17");
            Set<String> tempKey = chMap.keySet();
            Iterator<String> iterator1 = tempKey.iterator();
            if(HeartbeatClient.chargingPileState==1){
                while(iterator1.hasNext()) {
                    String key2 = iterator1.next();
                    if (Arrays.asList(fields).contains(key2)) {
                        int tempVal = HexUtil.makeRandom(255f, 0f, 0).intValue();
                        String hexStr = HexUtil.int2Hex(tempVal);
                        hexStr = HexUtil.getIntervalByteNum(hexStr, "0x17", key2);
                        chMap.put(key2, hexStr);
                    }
                }
            }
            map.put("0x17", chMap);
            channel.writeAndFlush(map);
        } catch (Exception e) {
            LOGGER.error("0x17报文发送异常：{}", e);
        }
    }

    /**
     * 0x18报文
     */
    public void send18Msg() {
        try {
            LOGGER.info("定时发送充电报文0x18——msgLog");
            Map<String, LinkedHashMap<String, String>> map = new GetHexMessage().getDataDomain(MsgTypeConst.CHARGE_MODEL_PARAM_SELECT_MSG_18);
            LinkedHashMap<String, String> chMap = map.get("0x18");
            Set<String> tempKey = chMap.keySet();
            Iterator<String> iterator1 = tempKey.iterator();
            if(HeartbeatClient.chargingPileState==1){
                while (iterator1.hasNext()) {
                    String key2 = iterator1.next();
                    if ("carVIN".equals(key2)) {
                        String vin = CarVINUtil.getRandomVin();
                        LOGGER.info("车辆VIN——msgLog：" + vin);
                        LOGGER.info("车辆VIN十六进制——msgLog：" + HexUtil.byteArrToHex(vin.getBytes()));
                        chMap.put(key2, HexUtil.byteArrToHex(vin.getBytes()));
                        break;
                    }
                }
            }
            map.put("0x18", chMap);
            channel.writeAndFlush(map);
        } catch (Exception e) {
            LOGGER.error("0x18报文发送异常：{}", e);
        }
    }
}
